package com.coding.mybatis;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.InputStream;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

/**
 * @ClassName XMLMapperBuilder
 * @Author ykx
 * @Date 2023/12/31 18:45
 * @Version 1.0
 */
public class XMLMapperBuilder {

    private Configuration configuration;

    public XMLMapperBuilder(Configuration configuration) {
        this.configuration = configuration;
    }

    public void parse(InputStream inputStream) throws DocumentException, ClassNotFoundException, NoSuchMethodException {
        Document document = new SAXReader().read(inputStream);
        Element root = document.getRootElement();

        String namespace = root.attributeValue("namespace");
        List<Element> selects = root.elements("select");

        for (Element child : selects) {
            String id = child.attributeValue("id");
            String parameterType = child.attributeValue("parameterType");
            String resultType = child.attributeValue("resultType");

            Class<?> parameterTypeClass = null;
            Class<?> resultTypeClass = getClassType(resultType);

            if (Objects.isNull(parameterType)) {
                parameterTypeClass = null;
            } else {
                parameterTypeClass = getClassType(parameterType);
            }

            // 如果是List集合，则找出泛型
            if (Collection.class.isAssignableFrom(resultTypeClass)) {
                Class<?> clazz = getClassType(namespace);
                Method method = clazz.getMethod(id);
                if (Objects.nonNull(parameterType)) {
                    method = clazz.getMethod(id, parameterTypeClass);
                }
                ParameterizedType returnType = (ParameterizedType) method.getGenericReturnType();
                resultTypeClass = (Class<?>) returnType.getActualTypeArguments()[0];
            }

            String key = namespace + "." + id;
            String sql = child.getTextTrim();

            MappedStatement mappedStatement = new MappedStatement();
            mappedStatement.setId(id);
            mappedStatement.setParameterType(parameterTypeClass);
            mappedStatement.setResultType(resultTypeClass);
            mappedStatement.setSql(sql);

            // 由于此处仅仅处理select标签，直接设置类型为SELECT
            mappedStatement.setType(SqlType.SELECT);
            configuration.getStatementMap().put(key, mappedStatement);
        }

    }

    private Class<?> getClassType(String className) throws ClassNotFoundException {
        return Class.forName(className);
    }

}
